<!DOCTYPE html>

<head>
    <title>HTML5 GetUserMedia Demo</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,
        maximum-scale=1.0" />
</head>

<body>
    <input type="button" title="开启摄像头" value="开启摄像头" onclick="getMedia();" /><br />
    <video height="120px" autoplay="autoplay"></video>
    <hr />
    <input type="button" title="拍照" value="拍照" onclick="getPhoto();" /><br />
    <canvas id="canvas1" height="120px"></canvas>
    <hr />
    <input type="button" title="视频" value="视频" onclick="getVedio();" /><br />
    <canvas id="canvas2" height="120px"></canvas>
    <div id="camMoveBox"></div>
    <style>
        #camMoveBox {
            position: absolute;
            left: 0;
            top: 500px;
            width: 100px;
            height: 100px;
            background-color: green;
            transition: all 100ms;
        }
        .point {
            position: fixed;
            background-color: red;
            width: 5px;
            height: 5px;
        }
    </style>
    <script type="text/javascript">
        var camHeight = 120;
        var camWidth = 160;
        var smallSize = 5;
        var wSize = 8*smallSize;
        var hSize = 6*smallSize;
        var colorWidth = 150;
        var usefulPointsNum = 10;
        var timeInter = 100;
        var video = document.querySelector('video');
        var audio, audioType;
        var lasPos = { x: 0, y: 0 };

        var canvas1 = document.getElementById('canvas1');
        var context1 = canvas1.getContext('2d');

        var canvas2 = document.getElementById('canvas2');
        var context2 = canvas2.getContext('2d');

        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
        window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

        var exArray = []; //存储设备源ID  
        // MediaStreamTrack.getSources(function (sourceInfos) {  
        //     for (var i = 0; i != sourceInfos.length; ++i) {  
        //         var sourceInfo = sourceInfos[i];  
        //         //这里会遍历audio,video，所以要加以区分  
        //         if (sourceInfo.kind === 'video') {  
        //             exArray.push(sourceInfo.id);  
        //         }  
        //     }  
        // });  

        function getMedia() {
            if (navigator.getUserMedia) {
                navigator.getUserMedia({
                    'video': {
                        'optional': [{
                            'sourceId': exArray[1] //0为前置摄像头，1为后置  
                        }]
                    },
                    'audio': true
                }, successFunc, errorFunc);    //success是获取成功的回调函数  
            }
            else {
                alert('Native device media streaming (getUserMedia) not supported in this browser.');
            }
        }

        function successFunc(stream) {
            console.log(stream);
            //alert('Succeed to get media!');  
            if (video.mozSrcObject !== undefined) {
                //Firefox中，video.mozSrcObject最初为null，而不是未定义的，我们可以靠这个来检测Firefox的支持  
                video.mozSrcObject = stream;
            }
            else {
                video.src = window.URL && window.URL.createObjectURL(stream) || stream;
            }

            //video.play();  

            // 音频  
            // audio = new Audio();  
            // audioType = getAudioType(audio);  
            // if (audioType) {  
            //     audio.src = 'polaroid.' + audioType;  
            //     audio.play();  
            // }  
        }
        function errorFunc(e) {
            alert('Error！' + e);
        }


        // 将视频帧绘制到Canvas对象上,Canvas每60ms切换帧，形成肉眼视频效果  
        function drawVideoAtCanvas(video, context) {
            window.setInterval(function () {
                context.translate(camWidth, 0);
                context.scale(-1, 1);
                context.drawImage(video, 0, 0, camWidth, camHeight);
            }, 60);
        }

        //获取音频格式  
        function getAudioType(element) {
            if (element.canPlayType) {
                if (element.canPlayType('audio/mp4; codecs="mp4a.40.5"') !== '') {
                    return ('aac');
                } else if (element.canPlayType('audio/ogg; codecs="vorbis"') !== '') {
                    return ("ogg");
                }
            }
            return false;
        }

        //vedio播放时触发，绘制vedio帧图像到canvas  
        //video.addEventListener('play', function () {  
        //      drawVideoAtCanvas(video, context2);  
        //}, false);  

        context1.translate(camWidth, 0);
        context1.scale(-1, 1);
        //拍照  
        function getPhoto() {
            context1.drawImage(video, 0, 0, camWidth, camHeight); //将video对象内指定的区域捕捉绘制到画布上指定的区域，实现拍照。
            getXy(context1);
        }

        setInterval(() => {
            context1.drawImage(video, 0, 0, camWidth, camHeight); //将video对象内指定的区域捕捉绘制到画布上指定的区域，实现拍照。
            getXy(context1);
            removeAllPoint();
        }, timeInter)

        //视频  
        function getVedio() {
            drawVideoAtCanvas(video, context2);
        }

        function getXy(ctx) {
            let image = ctx.getImageData(0, 0, camWidth, camHeight)
            console.log(image, image.width, image.height);
            for (let x = 0; x < image.width; x += smallSize) {
                for (let y = 0; y < image.height; y += smallSize) {
                    let color = getPixelColor(image, x, y);
                    // console.log(color);
                    setColor(x / smallSize, y / smallSize, getColorScore(color));
                }
            }
            console.log(window.activeArr);
            let pos = getMoveXy(window.activeArr);
            console.log(111);
            console.log(pos);

            if (lasPos.x - pos.x < 20 && lasPos.y - pos.y < 20) {
                if (pos.x * pos.y) {
                    // 平滑 但有延迟
                    document.getElementById('camMoveBox').style.left = ((pos.x + lasPos.x)/2 * wSize) + 'px';
                    document.getElementById('camMoveBox').style.top = ((pos.y + lasPos.y)/2 * hSize) + 'px';
                    // 实时
                    // document.getElementById('camMoveBox').style.left = (pos.x * wSize) + 'px';
                    // document.getElementById('camMoveBox').style.top = (pos.y * hSize) + 'px';
                    lasPos = pos;
                }
            } else if ((lasPos.x - pos.x) && (lasPos.y - pos.y)) {
                console.log('移动过快');
                let color = document.getElementById('camMoveBox').style.backgroundColor;
                if (color !=='red'){
                document.getElementById('camMoveBox').style.backgroundColor = 'red';
                setTimeout(() => {
                    document.getElementById('camMoveBox').style.backgroundColor = 'green';
                }, 500)
                }
            }
        }

        /*
         * 功能：获取图像中指定点的颜色值
         * @param Object obj 图像对象(getImageData()和createImageData())
         * @param Number x  图像中点的横坐标
         * @param Number y  图像中点的纵坐标\
         * @return Array 返回指定像素点颜色组成的数组
         */
        function getPixelColor(obj, x, y) {
            console.log('getPixelColor');
            var color = [];
            // 索引值获取方式：纵坐标*图像宽度+横坐标
            var index = y * obj.width + x;
            color.push(obj.data[index * 4 + 0]);
            color.push(obj.data[index * 4 + 1]);
            color.push(obj.data[index * 4 + 2]);
            color.push(obj.data[index * 4 + 3]);
            // 返回数组
            return color;
        }
        /*
         * 功能：设置图像中指定点的颜色值
         * @param Object obj 图像对象(getImageData()和createImageData())
         * @param Number x  图像中点的横坐标
         * @param Number y  图像中点的纵坐标
         * @param Array color 设置的颜色值(数组)
         * @return Array 返回指定像素点颜色组成的数组
         */
        function setPixelColor(obj, x, y, color) {
            // 将(100,100)颜色为红色
            var index = y * obj.width + x;
            // 设置代码
            obj.data[4 * index + 0] = color[0];
            obj.data[4 * index + 1] = color[1];
            obj.data[4 * index + 2] = color[2];
            obj.data[4 * index + 3] = color[3];
        }

        var arr = [];
        var activeArr = window.activeArr = [];
        function setColor(x, y, colorScore) {
            arr[y] = arr[y] || [];

            if (arr[y][x] == undefined) {
                arr[y][x] = colorScore;
            } else if (Math.abs(arr[y][x] - colorScore) > colorWidth) {
                activeArr[y] = activeArr[y] || [];
                activeArr[y][x] = 1;
                addPoint(x,y)
                arr[y][x] = colorScore;
            } else {
                activeArr[y] = activeArr[y] || [];
                activeArr[y][x] = 0;
                arr[y][x] = colorScore;
            }
        }
        function getColorScore(color) {
            return color[0] + color[1] + color[2];
        }

        function getMoveXy(activeArr) {
            let _w = camWidth / smallSize;
            let _h = camHeight / smallSize;
            let topX = 0;
            let topY = 0;
            let topXCount = 0;
            let topYCount = 0;
            let xArr = [];
            let yArr = [];

            for (let x = 0; x < _w; x++) {
                xArr[x] = xArr[x] || 0;
                for (let y = 0; y < _h; y++) {
                    xArr[x] += activeArr[y] ? (activeArr[y][x] || 0) : 0;
                }
            }
            for (let y = 0; y < _h; y++) {
                yArr[y] = yArr[y] || 0;
                for (let x = 0; x < _w; x++) {
                    yArr[y] += activeArr[y] ? (activeArr[y][x] || 0) : 0;
                }
            }
            for (let x = 0; x < _w; x++) {
                if (xArr[x] && (xArr[x] > topXCount || !topXCount)) {
                    topXCount += xArr[x] || 0;
                    topX += xArr[x] * x;
                }
            }
            for (let y = 0; y < _h; y++) {
                if (yArr[y] && (yArr[y] > topYCount || !topYCount)) {
                    topYCount += yArr[y] || 0;
                    topY += yArr[y] * y;
                }
            }
            console.log(topX, topY, topXCount, topYCount)
            if (topXCount + topYCount > usefulPointsNum) {
                topX = topX / topXCount;
                topY = topY / topYCount;
            } else {
                topX = NaN;
                topY = NaN;
            }
            return {
                x: topX,
                y: topY
            }
        }

        function addPoint(x,y) {
            let point = document.createElement('div');
            point.className = 'point';
            point.style.left = x*wSize + 'px';
            point.style.top = y*hSize + 'px';
            document.body.appendChild(point);
        }
        function removeAllPoint() {
            let points = document.getElementsByClassName('point');
            [].forEach.call(points, (point)=>{
                document.body.removeChild(point);
            })
        }
    </script>
</body>